diff options
Diffstat (limited to 'app/[lng]/evcp')
| -rw-r--r-- | app/[lng]/evcp/(evcp)/(system)/approval/log/[apInfId]/approval-log-detail-view.tsx | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/app/[lng]/evcp/(evcp)/(system)/approval/log/[apInfId]/approval-log-detail-view.tsx b/app/[lng]/evcp/(evcp)/(system)/approval/log/[apInfId]/approval-log-detail-view.tsx index 80cf4379..eb59fb28 100644 --- a/app/[lng]/evcp/(evcp)/(system)/approval/log/[apInfId]/approval-log-detail-view.tsx +++ b/app/[lng]/evcp/(evcp)/(system)/approval/log/[apInfId]/approval-log-detail-view.tsx @@ -3,9 +3,14 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Separator } from "@/components/ui/separator"; +import { Button } from "@/components/ui/button"; import { ApprovalLogDetail } from "@/lib/approval-log/service"; import { formatDate } from "@/lib/utils"; -import { Clock, Mail, User, FileText, Shield, AlertCircle, CheckCircle, XCircle, Zap } from "lucide-react"; +import { Clock, Mail, User, FileText, Shield, AlertCircle, CheckCircle, XCircle, Zap, PlayCircle } from "lucide-react"; +import { forcePostProcessApproval } from "@/lib/approval-log/actions"; +import { toast } from "sonner"; +import { useRouter } from "next/navigation"; +import { useState } from "react"; interface ApprovalLogDetailViewProps { detail: ApprovalLogDetail; @@ -13,6 +18,38 @@ interface ApprovalLogDetailViewProps { export function ApprovalLogDetailView({ detail }: ApprovalLogDetailViewProps) { const { approvalLog, pendingAction } = detail; + const router = useRouter(); + const [isProcessing, setIsProcessing] = useState(false); + + // pendingAction이 있으면 후처리 버튼 표시 (서버에서 검증) + const canPostProcess = !!pendingAction; + + const handlePostProcess = async () => { + if (isProcessing) return; + + setIsProcessing(true); + try { + const result = await forcePostProcessApproval(approvalLog.apInfId); + + if (result.success) { + toast.success('후처리 성공', { + description: result.message, + }); + // 페이지 새로고침 + router.refresh(); + } else { + toast.error('후처리 실패', { + description: result.error, + }); + } + } catch (error) { + toast.error('후처리 오류', { + description: error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다.', + }); + } finally { + setIsProcessing(false); + } + }; // 상태 텍스트 변환 const getStatusText = (status: string) => { @@ -252,13 +289,28 @@ export function ApprovalLogDetailView({ detail }: ApprovalLogDetailViewProps) { {pendingAction && ( <Card> <CardHeader> - <CardTitle className="flex items-center gap-2"> - <CheckCircle className="h-5 w-5" /> - 액션 정보 - </CardTitle> - <CardDescription> - 결재와 연결된 Pending Action 정보입니다. - </CardDescription> + <div className="flex items-center justify-between"> + <div> + <CardTitle className="flex items-center gap-2"> + <CheckCircle className="h-5 w-5" /> + 액션 정보 + </CardTitle> + <CardDescription> + 결재와 연결된 Pending Action 정보입니다. + </CardDescription> + </div> + {canPostProcess && ( + <Button + onClick={handlePostProcess} + disabled={isProcessing || pendingAction.status === 'executed'} + size="sm" + variant={pendingAction.status === 'executed' ? 'outline' : 'default'} + > + <PlayCircle className="mr-2 h-4 w-4" /> + {isProcessing ? '처리중...' : pendingAction.status === 'executed' ? '후처리 완료됨' : '후처리 실행'} + </Button> + )} + </div> </CardHeader> <CardContent className="space-y-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> |
